package com.hwtx.protocol.dubbo.code;

import com.hzgj.bcl.soa.net.Encoder;
import com.hzgj.bcl.soa.rpc.message.Message;
import com.hzgj.bcl.soa.util.Bytes;
import com.hzgj.bcl.soa.util.Constants;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import static com.hwtx.protocol.dubbo.code.DubboConstants.DUBBO_PROTOCOL;
import static com.hwtx.protocol.dubbo.code.DubboConstants.FLAG_EVENT;
import static com.hwtx.protocol.dubbo.code.DubboConstants.FLAG_REQUEST;
import static com.hwtx.protocol.dubbo.code.DubboConstants.FLAG_TWOWAY;
import static com.hwtx.protocol.dubbo.code.DubboConstants.HEADER_LENGTH;
import static com.hwtx.protocol.dubbo.code.DubboConstants.MAGIC;
import static com.hwtx.protocol.dubbo.code.DubboConstants.OK;
import static com.hwtx.protocol.dubbo.code.DubboConstants.SERVER_ERROR;
import static com.hzgj.bcl.soa.net.DefaultEncoder.checkPayload;

public class DubboEncoder extends Encoder {

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {

        // header.
        byte[] header = new byte[HEADER_LENGTH];
        // set magic number.
        Bytes.short2bytes(MAGIC, header);

        boolean isEvent = msg.getHeader(Constants.MESSAGE_HEADER_EVENT) != null;

        if (isEvent) {
            header[2] |= FLAG_EVENT;
        }

        Integer type = (Integer) msg.getHeader(Constants.MESSAGE_TYPE);

        // set request and serialization flag and status
        switch (type) {
            case Message.EXC_RSP:
                header[3] = SERVER_ERROR;
                header[2] = msg.getSerializationId();
                break;
            case Message.REQ:
                header[3] = 20;//dubbo请求转换为20
                header[2] = (byte) (FLAG_REQUEST | msg.getSerializationId());
                break;
            case Message.RSP:
                header[3] = OK;
                header[2] = msg.getSerializationId();
                break;
        }

        // twoway default
        header[2] |= FLAG_TWOWAY;

        // set request id.
        Bytes.long2bytes((long) msg.getHeader(Constants.MESSAGE_SID), header, 4);

        int savedWriteIndex = out.writerIndex();
        out.writerIndex(savedWriteIndex + HEADER_LENGTH);
        out.writeBytes((byte[]) msg.getPayload());
        int len = msg.getLength();
        checkPayload(ctx.channel(), len);
        Bytes.int2bytes(len, header, 12);

        out.writerIndex(savedWriteIndex);
        // write header.
        out.writeBytes(header);
        out.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
    }

    @Override
    public String getName() {
        return DUBBO_PROTOCOL;
    }
}